package com.yc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysql.cj.util.StringUtils;
import com.yc.common.utils.AlyExcelUtil;
import com.yc.common.utils.ValueUtils;
import com.yc.entity.*;
import com.yc.enums.ClassTime;
import com.yc.exception.BizException;
import com.yc.exception.CustomException;
import com.yc.mapper.ScheduleMapper;
import com.yc.mapper.StudentInfoMapper;
import com.yc.mapper.UserMapper;
import com.yc.service.ScheduleService;
import com.yc.vo.AttendanceData;
import com.yc.vo.Result;
import com.yc.vo.StudentAttendanceRecord;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yc.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.yc.mapper.AttendanceMapper;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 考勤表;(attendance)表服务实现类
 *
 * @date : 2023-6-28
 */
@Service
public class AttendanceServiceImpl implements AttendanceService{
    @Resource
    private AttendanceMapper attendanceMapper;
    @Resource
    private AttendanceRecordsService attendanceRecordsService;
    @Resource
    private ScheduleMapper scheduleMapper;
    @Autowired
    private UserMapper userMapper;
    @Resource
    private StudentInfoMapper studentInfoMapper;

    @Resource
    private ScheduleService scheduleService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Attendance queryById(Integer id) {
        return attendanceMapper.selectById(id);
    }

    /**
     * 分页查询
     *
     * @param attendance 筛选条件
     * @param current 当前页码
     * @param size  每页大小
     * @return
     */
    @Override
    public Page<Attendance> paginQuery(Attendance attendance, long current, long size){
        //1. 构建动态查询条件
        LambdaQueryWrapper<Attendance> queryWrapper = new LambdaQueryWrapper<>();
        if(StrUtil.isNotBlank(attendance.getStuid())){
            queryWrapper.eq(Attendance::getStuid, attendance.getStuid());
        }
        if(StrUtil.isNotBlank(attendance.getDate())){
            queryWrapper.eq(Attendance::getDate, attendance.getDate());
        }
        if(StrUtil.isNotBlank(attendance.getRemarks())){
            queryWrapper.eq(Attendance::getRemarks, attendance.getRemarks());
        }
        if(StrUtil.isNotBlank(attendance.getImagepath())){
            queryWrapper.eq(Attendance::getImagepath, attendance.getImagepath());
        }
        //2. 执行分页查询
        Page<Attendance> pagin = new Page<>(current , size , true);
        IPage<Attendance> selectResult = attendanceMapper.selectByPage(pagin , queryWrapper);
        pagin.setPages(selectResult.getPages());
        pagin.setTotal(selectResult.getTotal());
        pagin.setRecords(selectResult.getRecords());
        //3. 返回结果
        return pagin;
    }

    /**
     * 新增数据
     *
     * @param attendance 实例对象
     * @return 实例对象
     */
    @Override
    public Attendance insert(Attendance attendance){
        attendanceMapper.insert(attendance);
        return attendance;
    }

    /**
     * 更新数据
     *
     * @param attendance 实例对象
     * @return 实例对象
     */
    @Override
    public Attendance update(Attendance attendance) {
        //1. 根据条件动态更新
        LambdaUpdateChainWrapper<Attendance> chainWrapper = new LambdaUpdateChainWrapper<Attendance>(attendanceMapper);
        if (StrUtil.isNotBlank(attendance.getStuid())) {
            chainWrapper.eq(Attendance::getStuid, attendance.getStuid());
        }
        if (StrUtil.isNotBlank(attendance.getDate())) {
            chainWrapper.eq(Attendance::getDate, attendance.getDate());
        }
        if (StrUtil.isNotBlank(attendance.getRemarks())) {
            chainWrapper.eq(Attendance::getRemarks, attendance.getRemarks());
        }
        if (StrUtil.isNotBlank(attendance.getImagepath())) {
            chainWrapper.eq(Attendance::getImagepath, attendance.getImagepath());
        }
        //2. 设置主键，并更新
        chainWrapper.set(Attendance::getId, attendance.getId());
        boolean ret = chainWrapper.update();
        //3. 更新成功了，查询最最对象返回
        if (ret) {
            return queryById(attendance.getId());
        } else {
            return attendance;
        }
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        int total = attendanceMapper.deleteById(id);
        return total > 0;
    }

    /**
     * 上传数据
     *
     * @param inputStream 数据流
     * @return 是否成功
     */
    @Override
    public int upload(InputStream inputStream, String notes, String id) {
        //解析多个表格的多个sheet
        List<List<Map<String, Object>>> sheets = AlyExcelUtil.excelToShopIdList(inputStream);
        int size = sheets.size();
        // TODO 待优化
        for (int i = 0; i < size; i++) {
            List<Map<String, Object>> maps = sheets.get(i);
            //班级名称
            String[] classIds = maps.get(0).get("3").toString().split(":")[1].split(",");
            //课表id
            String scheduleid = maps.get(0).get("4").toString().split(":")[1];
            //先查看是否重复上传
            Attendance attendance1 = attendanceMapper.queryByScheduleId(scheduleid);
            if(attendance1!=null){
                continue;
            }

            //插入考勤表信息
            Attendance attendance = new Attendance();
            //老师id
            attendance.setTeacherid(scheduleMapper.selectById(scheduleid).getTeacherid());
            //班长或者学委的学号
            StringBuffer sb = new StringBuffer();
            for (String classId : classIds) {
                //先将班级学生全部查出来
                List<StudentInfo> studentInfos = studentInfoMapper.queryAllByClassId(classId);

                attendance.setSignmethod(0);
                for (StudentInfo studentInfo : studentInfos) {
                    String spare = studentInfo.getSpare();
                    if ("1".equals(spare) || "2".equals(spare)) {
                        sb.append(studentInfo.getStuid()).append(",");
                        break;
                    }
                }
            }
            attendance.setStuid(sb.toString());
            attendance.setScheduleid(Integer.valueOf(scheduleid));
            attendance.setDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            attendance.setRemarks(notes);

            //已到人数
            int arriveNum = 0;
            List<AttendanceRecords> list = new ArrayList<>();

            for (int j = 3; j < maps.size(); j++) {
                Map<String, Object> map = maps.get(j);
                AttendanceRecords attendanceRecords = new AttendanceRecords();
                attendanceRecords.setStuid(map.get("1") + "");
                String status = map.get("3").toString().trim();
                int result = 0;

                switch (status) {
                    case "已到":
                        result = 1;
                        arriveNum++;
                        break;
                    case "请假":
                        result = 2;
                        break;
                    case "迟到":
                        result = 3;
                        break;
                    case "早退":
                        result = 4;
                        break;
                    case "旷课":
                        result = 5;
                        break;
                    default:
                        //非法字符
                        result = 6;
                        break;
                }
                if (result == 6) {
                    //有未识别的字符，返回那一行
                    return j + 3;
                }

                attendanceRecords.setStatus(result);
                list.add(attendanceRecords);
            }
            attendance.setArrivedcount(arriveNum);
            attendanceMapper.insert(attendance);
            if(list.size() == 0){
                continue;
            }
            list.forEach(d->{
                d.setAttid(attendance.getId());
            });
            attendanceRecordsService.insert(list, id);
        }
        return 0;
    }

    public void demo(String schoolYear, String i, List<String> weeks){
        attendanceMapper.addWeek(schoolYear, i, weeks);
    }

    /**
     * 通过考勤表Id查询上课的学生
     * @param attId 考勤表Id
     * @return
     */
    public List<StudentAttendanceRecord> selectStudentByAttId(String attId){
        return attendanceMapper.selectStudentByAttId(attId);
    }
    /**
     * 添加考勤信息
     * @param attendance 考勤信息
     */
    public void addAttendance(Attendance attendance){
        int res = attendanceMapper.addAttendance(attendance);
        if (res <= 0){
            throw new CustomException("0", "考勤失败!请联系管理员");
        }
    }

    /**
     * 通过课程Id查询是否有考勤记录 没有则新增 有就修改
     * @param scheduleId
     * @return 考勤记录
     */
    public Integer selectAttendanceByScheduleId(String scheduleId){
        return attendanceMapper.selectAttendanceByScheduleId(scheduleId);
    }

    /**
     * 修改考勤信息
     * @param attendance 考勤信息
     * @return  1成功 0失败
     */
    public void modifyAttendance(Attendance attendance){
        int res = attendanceMapper.modifyAttendance(attendance);
        if (res <= 0){
            throw new CustomException("0", "考勤失败!请联系管理员");
        }
    }

    /**
     * 分页 通过考勤表Id查询上课的学生
     * @param attId 考勤表Id
     * @return
     */
    public Page<StudentAttendanceRecord> selectPageStudentByAttId(Page<StudentAttendanceRecord> page, String attId){
        return attendanceMapper.selectPageStudentByAttId(page, attId);
    }

    /**
     * 查询学生 有考勤的年份
     * @param stuid 学生学号
     * @return 有考勤的年份
     */
    public List<String> selectAllYears(String stuid){
        List<String> years = attendanceMapper.selectAllYears(stuid);
        if (years.size() <= 0){
            throw new CustomException("0", "暂无数据");
        }
        return years;
    }

    /**
     * 查询学生 有考勤的月份
     * @param beginDate 起始时间
     * @param endDate   截止时间
     * @return  有考勤的月份
     */
    public List<String> selectAllMonths(String beginDate, String endDate){
        List<String> months = attendanceMapper.selectAllMonths(beginDate, endDate);
        if (months.size() <= 0){
            throw new CustomException("0", "该年暂无数据");
        }
        return months;
    }

    /**
     * 下载批量添加学生的模板
     *
     * @param response
     * @return
     * @throws IOException
     */
    public Result<?> downloadTemplate(HttpServletResponse response) throws IOException {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        org.springframework.core.io.Resource[] resources = resourcePatternResolver.
                getResources("classpath*:" + File.separator + "static" +
                        File.separator + "file" + File.separator + "template.xls");
        org.springframework.core.io.Resource resource = resources[0];
        InputStream inputStream = null;
        OutputStream out = null;
        try {
            //根据文件在服务器的路径读取该文件转化为流
            inputStream = resource.getInputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String time = simpleDateFormat.format(date);
            String fileName = "辅导员带班信息模板-" + time + ".xlsx";
            //设置文件ContentType类型，这样设置，会自动判断下载文件类型
            response.setContentType("multipart/form-data");
            //设置文件头：最后一个参数是设置下载文件名（设置编码格式防止下载的文件名乱码）
            response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("UTF-8"), "ISO8859-1"));
            out = response.getOutputStream();
            int b = 0;
            while (b != -1) {
                b = inputStream.read(buffer);
                //写到输出流(out)中
                out.write(buffer, 0, b);
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(1, "下载失败");
        } finally {
            try {
                inputStream.close();
                out.close();
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 快捷考勤
     * @param attendanceDataList 班级集合
     * @return
     */
    @Override
    public Integer addQuick(List<AttendanceData> attendanceDataList) throws BizException {
        for (int i = 0; i < attendanceDataList.size(); i++) {
            ValueUtils.check(ValueUtils.isEmpty(attendanceDataList.get(i).getArrivedcount()),"实到人数不能为空");
            if ("0".equals(attendanceDataList.get(i).getArrivedcount())){
                throw new BizException("实到人数不能为0");
            }
            final String[] split = attendanceDataList.get(i).getImage().split(",");
            if (split.length<1||StringUtils.isNullOrEmpty(attendanceDataList.get(i).getImage())){
                throw new BizException("至少上传一张照片");
            }
        }
        final Integer integer = attendanceMapper.addQuick(attendanceDataList);
        return integer;
    }
}
